package com.gc.cscott.providers;

import com.gc.cscott.domain.contest.Contest;
import com.gc.cscott.domain.contest.Task;
import com.gc.cscott.domain.contest.TestCase;
import com.gc.cscott.domain.contest.numbers.TaskNumber;
import com.gc.cscott.domain.contest.numbers.TestCaseNumber;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.inject.Provider;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import org.apache.commons.io.FileUtils;

/**
 *
 * @author root
 */
public class ContestProvider implements Provider<Contest> {
    private static final File configurationFile = new File("contest.json");

    public Contest get() {
        try {
            Gson gson = new GsonBuilder().serializeNulls()
                    .registerTypeAdapter(TaskNumber.class,
                        new JsonDeserializer(){
                            public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                                return new TaskNumber(json.getAsInt());

                            }
                    })
                    .registerTypeAdapter(TestCaseNumber.class,
                        new JsonDeserializer(){
                            public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                                return new TestCaseNumber(json.getAsInt());

                            }
                    })
                    .create();
            if (configurationFile.exists() == false) {
                try {
                    FileUtils.writeStringToFile(configurationFile, gson.toJson(new Contest()));
                } catch (IOException e) {
                    throw new Error("Failed to create configuration template file at: " + configurationFile.getAbsolutePath());
                }
            }
            String contestJson = FileUtils.readFileToString(configurationFile);
            Contest contest = gson.fromJson(contestJson, Contest.class);

            if (contest.getName()==null){
                throw new Error("Missed property 'name': "+configurationFile.getAbsolutePath());
            }
            if (contest.getTaskDir()==null){
                throw new Error("Missed property 'taskDir': "+configurationFile.getAbsolutePath());
            }
            if (contest.getWorkDir()==null){
                throw new Error("Missed property 'workDir': "+configurationFile.getAbsolutePath());
            }
            if (contest.getSourcesList()==null){
                throw new Error("Missed property 'sourcesList': "+configurationFile.getAbsolutePath());
            }
            if (contest.getTasksList()==null){
                throw new Error("Missed property 'tasksList': "+configurationFile.getAbsolutePath());
            }
            for(Task task:contest.getTasksList()){
                task.setContest(contest);
                if (task.getName()==null){
                    throw new Error("Missed property 'tasksList[i].name': "+configurationFile.getAbsolutePath());
                }
                if (task.getRelativeDir()==null){
                    throw new Error("Missed property 'tasksList[i].relativeDir': "+configurationFile.getAbsolutePath());
                }
                if (task.getTimeout()<=0){
                    throw new Error("Missed property 'tasksList[i].timeOut': "+configurationFile.getAbsolutePath());
                }
                if (task.getTestCaseList()==null){
                    throw new Error("Missed property 'tasksList[i].testCaseList': "+configurationFile.getAbsolutePath());
                }
                for(TestCase testCase:task.getTestCaseList()){
                    testCase.setTask(task);
                    if (testCase.getTimeout()<=0){
                        throw new Error("Wrong timeout (<0), 'tasksList[i].testCaseList[j].timeout': "+configurationFile.getAbsolutePath());
                    }
                }
            }
            return contest;
        } catch (IOException ex) {
            throw new Error("Contest configuration not found at: " + configurationFile.getAbsolutePath(), ex);
        }
    }
}
